# -*- coding:utf-8 -*-
from framework.interface.abstract_api import AbstractApi
from marshmallow import Schema, fields, validate
from datetime import datetime, timedelta
import pandas as pd
import numpy as np
from collections import namedtuple
import os
import json
from flask import request
import requests
import uuid
import subprocess
from docx import Document
from docx.shared import Pt
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
import requests
from io import BytesIO
class RobotAgent(AbstractApi):
    """
    接口：RobotAgent
    文件名输入：robot_agent
    该接口访问地址为：http://10.10.30.247:9091/v1/robot-agent
    输入：
    功能：
    输出：
    """

    class GetSchema(Schema):
        pass

    def handle_get_request(self):
        try:
            output1 = self.get_online_data()
            return output1
        except Exception as e:
            return f"程序异常: {str(e)}", 500

    # 业务1
    def get_online_data(self):
        # 0 拟题摘要  1 问题分析  2.问题假设  【【3】】.符号说明 4.模型求解以及建立  【5】.灵敏度分析  【6】.模型评价  【7】.模型改进 【8】.参考文献 【9】.附录
        quel=["""请请严格根据这个摘要格式:  （先拟题,拟题的题目用{}包裹起来） 拟题：该摘要的拟题  （换行） 摘 要 

本论文旨在设计并优化定日镜场模型，以尽可能高效地收集太阳能。定日镜场通过其反射装置将太阳光集中至吸收塔集热器上，从而实现能量转换。我们首先对定日镜场中的光学损失进行了详细分析，包括阴影遮挡、余弦损失和集热器截断效率，并建立了相应的计算模型。为了精确计算定日镜场的效率，我们构建了三个坐标系：镜场大地坐标系、镜面坐标系和光锥束坐标系，并根据这些坐标系计算入射光线和反射光线。

对于问题一，我们利用数值方法，以1米的步长在特定定日镜上创建网格化光锥束，并计算年平均光学效率、年平均热功率和单位镜面面积年平均输出热功率。此外，我们还探讨了步长对计算结果稳健性的影响。

针对问题二，我们提出了一个优化模型，目标是最大化单位镜面面积年平均输出热功率。在此模型中，我们考虑了吸收塔位置、定日镜的尺寸、安装高度、数量和位置等决策变量，并设置了具体的约束条件。使用蜂窝排列法和蒙特卡洛模拟对这些变量进行取样，尝试找到最佳的设定组合。

最后，针对问题三，在定日镜尺寸和安装高度可以不同的前提下，我们进一步优化了定日镜场的配置。我们考虑了额定功率、相邻定日镜的间距以及圆形区域半径等因素，并在此基础上，提高了最外围定日镜的安装高度，以期达到更好的性能表现。

关键词：坐标旋转、光学效率、输出热功率、锥形光束、蜂窝排列法

），请你详细的写数学建模竞赛的摘要，要求详细，有思路和方案。文本中关键的模型算法名词用{}包裹起来，关键词写5个就行。请为本赛题生成一篇有深度的摘要，不要生成其它无关内容：""",
              """请你根据本上述提到的摘要内容以及要求的格式排版(大括号别去掉)： \n\n
{问题分析} (换2行)
 1.1 {问题一的分析}  (换2行) (写内容)
 1.2 {问题二的分析}  (换2行) (写内容)
 1.3 {问题三的分析}  (换2行) (写内容)
 1.4 {问题四的分析}  (换2行) (写内容)
 ... ...

写出对这几个问题的深入解题思路(文本中关键的模型算法名词用{}包裹起来,不要有其它内容）""",
              """请根据上述提到的问题分析，给出模型假设（要求格式：
{模型假设}  (换行)
为了对模型进行合理的优化，我们建立了以下的模型假设 /n
1.假设... (换2行)  2.假设...(换2行)  3.假设... (换2行) 4.假设...(换2行) 5.假设... (换2行) 6.假设...(换2行)  ... ...  不要有其它内容.)""",
              """基于上述提到的问题分析，给出问题分析所需涉及的符号说明 （要求格式：
        grades = [
            ('Q', "水流量", "/m^3/s"),  # 表示黄河水文站上水流的体积流量
            ('S', "含沙量", "/kg/m^3"),  # 表示单位体积水中所含沙土的质量
            ('t', "时间", ""),  # 表示观测或监测的具体时间点
            ('H', "水位高度", "/m"),  # 表示相对于“1985 国家高程基准”的水位高度
            ('T_s', "年总水流量", "/m^3"),  # 表示某一年内黄河水文站的累积水流量
            ('T_ss', "年总排沙量", "/kg"),  # 表示某一年内黄河水文站通过水排出的累积沙量
            ('d', "断面距离起点", "/m"),  # 表示黄河断面上某点与规定起点的直线距离
            ('B_elev', "河底高程", "/m"),  # 表示河底相对于“1985 国家高程基准”的高度
        ] 不要有其它内容. )""",
 """请你根据问题一上面的思路，请你给出要求格式：（ 模型建立与求解 (换行) (换行)   1.1 {基于问题一...的模型建立}  (换行)    (换行)  ...(请你说出详细的建立公式)  1.2 {基于问题一...的求解过程}   (换行)    (换行)  ...   1.3 {基于问题一...的求解代码}   (换行)    (换行)  ...    1.4 {结论}   (换行)    (换行)  ...   ） （关键术语粗用{}包裹，不要输出其它内容. ）：""",
              """请你根据问题二上面的思路，请你给出要求格式：（ 模型建立与求解 (换行) (换行)   1.1 {基于问题二...的模型建立}  (换行)    (换行)  ...(请你说出详细的建立公式)  1.2 {基于问题二...的求解过程}   (换行)    (换行)  ...   1.3 {基于问题二...的求解代码}   (换行)    (换行)  ...    1.4 {结论}   (换行)    (换行)  ...   ） （关键术语粗用{}包裹，不要输出其它内容. ）：""",
              """请你根据问题三上面的思路，请你给出要求格式：（ 模型建立与求解 (换行) (换行)   1.1 {基于问题三...的模型建立}  (换行)    (换行)  ...(请你说出详细的建立公式)  1.2 {基于问题三...的求解过程}   (换行)    (换行)  ...   1.3 {基于问题三...的求解代码}   (换行)    (换行)  ...    1.4 {结论}   (换行)    (换行)  ...   ） （关键术语粗用{}包裹，不要输出其它内容. ）：""",
              """请你根据问题四上面的思路，请你给出要求格式：（ 模型建立与求解 (换行) (换行)   1.1 {基于问题四...的模型建立}  (换行)    (换行)  ...(请你说出详细的建立公式)  1.2 {基于问题四...的求解过程}   (换行)    (换行)  ...   1.3 {基于问题四...的求解代码}   (换行)    (换行)  ...    1.4 {结论}   (换行)    (换行)  ...   ） （关键术语粗用{}包裹，不要输出其它内容. ）：""",
              """请你根据上面的采用的算法细节，详细进行灵敏度分析，并给出灵敏度分析代码，每段首行缩进四个空格（请直接写内容）：""",
              """ 请你根据上面的采用的算法思路，详细写出几段采用上述算法的模型优缺点评价，每段首行缩进四个空格（请直接写内容）：""",
        """请你根据上面的采用的算法思路，详细写出几段采用上述算法的基础是的优化和改进方案，每段首行缩进四个空格（请直接写内容）：""","""
        请你根据上面的采用的算法思路，详细写模仿10个参考文献（请直接写内容 格式： 【1】....... (换行)  【2】.......(换行) 【3】.....）：""","""
        告诉我需要展示哪些需要的附录内容（列表形式）""",

              ]
        sql = f"""
                   select file_content,name_ids from maxstudio_files_table
  left join admin on admin.ids = maxstudio_files_table.name_ids
          where created_at >=CURDATE()  and emial is not null  and emial !='0' 
            and file_type like  '%数学建模赛题%'
            and is_status=0;
                """
        urllist=[]
        url_pdf_list=[]
        output = pd.DataFrame(self.sql_db.list(sql))
        seta_history_content=[output['file_content'][0]]
        name_ids=[output['name_ids'][0]]
        for k in range(len(quel)):
            print("*"*30,f"目前所处的阶段{k}")
            text = ''.join(seta_history_content)
            print("目前需要处理阶段性的内容",text)
            texadr = str(uuid.uuid4())
            data = self.maxstudio_model(text, quel[k])
            seta_history_content.append(data)
            # 输出存储 形式 ----- 灵敏度  评价 改进 参考文献 附录--------------------------
            if k ==8or k ==9 or k==10 or k==11 or k==12:
                # API endpoint
                url = "http://106.53.97.117:7777/v1/part-ohter"
                # 请求体数据
                texdata = {
                    "part_id":f"{texadr}",
                    "part_type_id":k,
                    "part_youque":data

                }
                # 设置headers参数，如果API需要的话
                headers = {
                    'Content-Type': 'application/json',  # 可能需要设置正确的内容类型
                    # 添加其他可能需要的headers
                }
                # 发送POST请求
                response = requests.post(url, headers=headers, json=texdata)  # 启用stream模式
                print("*"*40,response.json())
                url = f"http://106.53.97.117:7777/static/m{texadr}.docx"
                urllist.append(url)
                pdfurl = f"http://106.53.97.117:7777/static/m{texadr}.pdf"
                url_pdf_list.append(pdfurl)
            elif k ==3:
                # API endpoint
                url = "http://106.53.97.117:7777/v1/part-zhaiyao"
                # 请求体数据
                texdata = {
                    "part_id":f"{texadr}",
                    "part_zhaiyao":data
                }
                # 设置headers参数，如果API需要的话
                headers = {
                    'Content-Type': 'application/json',  # 可能需要设置正确的内容类型
                    # 添加其他可能需要的headers
                }
                # 发送POST请求
                response = requests.post(url, headers=headers, json=texdata)  # 启用stream模式
                print("*"*40,response.json())
                url = f"http://106.53.97.117:7777/static/m{texadr}.docx"
                urllist.append(url)
                pdfurl = f"http://106.53.97.117:7777/static/m{texadr}.pdf"
                url_pdf_list.append(pdfurl)
            else:
                # 设置相对路径
                relative_path = os.path.join('..', 'src/static')
                # 检查目录是否存在，如果不存在，则创建它
                if not os.path.exists(relative_path):
                    os.makedirs(relative_path)
                # 现在我们确认目录存在，可以安全地写入文件
                filename_tex = f'm{texadr}.tex'
                with open(os.path.join("/home/lighthouse/studiomianserver/static/", filename_tex), 'w') as f:
                    f.write(data)
                filename_md = f'm{texadr}.md'
                with open(os.path.join("/home/lighthouse/studiomianserver/static/", filename_md), 'w') as f:
                    f.write(data)
                self.convertdoc(f"{texadr}")
                url = f"http://106.53.97.117:2088/static/m{texadr}.docx"
                urllist.append(url)
                pdfurl = f"http://106.53.97.117:2088/static/m{texadr}.pdf"
                url_pdf_list.append(pdfurl)
        print("到底发生了啥？？？",url_pdf_list,urllist)
        # 合并docx 转化为pdf
        urldocx,docx_path = self.combine_docxs(urllist)
        # urldocx,docx_path = "",""
        # 存储地址
        merged_url = f"http://106.53.97.117:7777/static/{self.combine_pdf(url_pdf_list)}"
        # 更新该用户状态
        user_status = self.compelte_user(name_ids)
        #  到用户  并QQ邮箱通知 对应用户 查询name_ids对应用户的邮箱信息
        try:
            user_emial_sql = f"""select emial from admin where ids ={name_ids[0]}"""
            user_emial = self.sql_db.value(user_emial_sql)
        except Exception as e:
            print(e)
            user_emial="z15221500166@163.com"
        emial_status=self.send_email(user_emial,self.combine_pdf(url_pdf_list),docx_path)

        # 将url地址更新到数据库
        try:
            sql=f"update  maxstudio_files_table set combne_pdf ='{merged_url}',combine_docx='{urldocx}' where name_ids ={name_ids[0]} "
            result=self.sql_db.query(sql)
            spdf_docx_status=result
        except Exception as e:
            spdf_docx_status="false"


        return {"urllist_docxs":urllist,"url_pdf_list":url_pdf_list,"combine_url_docx":urldocx,"url_pdf":merged_url,"user_status":user_status,"email_status":emial_status,"spdf_docx_status":spdf_docx_status}

    # g4请求体
    def maxstudio_model(self,text,ques):

        # API endpoint
        url = "http://math-x-studio.cn/api/chat-process"

        # 请求体数据
        data = {
            "prompt": ques+text,
            # "prompt": "你是谁啊",
            "options": {
                "parentMessageId": "chatcmpl-9KlLjLOurcK6hexY9KEEvhvP0V4xw"
            },
            "systemMessage":"你是一个深度的数学建模论文框架生成工具并且输出严格按照promot要求",
            "temperature": 0.9,
            "top_p": 1
        }

        # 设置headers参数，如果API需要的话
        headers = {
            'Content-Type': 'application/json',  # 可能需要设置正确的内容类型
            # 添加其他可能需要的headers
        }

        # 发送POST请求
        response = requests.post(url, headers=headers, json=data, stream=True)  # 启用stream模式

        # 处理流式响应
        last_line = None
        for line in response.iter_lines():
            if line:
                last_line = line.decode('utf-8')  # 解码字节流至文字

        # 将最后一行文本转换为JSON对象
        if last_line:
            last_json = json.loads(last_line)
            print("最后一条信息：", last_json['text'])  # 打印最后一条JSON信息
        else:
            last_json=""
        return last_json['text']

    def convertdoc(self,texadr):
        url = "http://106.53.97.117:2088/convertdoc"
        # 设置headers参数，如果API需要的话
        headers = {
            'Content-Type': 'application/json',  # 可能需要设置正确的内容类型
            # 添加其他可能需要的headers
        }
        data = {
            "id":texadr
        }
        res=requests.post(url,json=data,headers=headers)
        print(res.json(),"测试结果")
        return "1"

#     合并docx
    def combine_docxs(self,docx_fileslist):
        texadr=str(uuid.uuid4())
        # 这是你想合并的docx文件的URL列表
        docx_files = docx_fileslist
        # 创建一个新的Document对象，用于存储合并后的内容
        merged_document = Document()
        print(docx_fileslist,"这次能否成功存储呢？")
        for url in docx_files:
            # 下载每个docx文件
            response = requests.get(url)
            # 检查请求是否成功
            # 将内容写入临时文件
            temp_docx_filename = 'tempfile.docx'
            with open(temp_docx_filename, 'wb') as f:
                f.write(response.content)
            # 打开临时文件并将其内容添加到合并的文档中
            temp_document = Document(temp_docx_filename)
            for element in temp_document.element.body:
                merged_document.element.body.append(element)
        merged_document.save(f'static/combine_{texadr}.docx')
        return f"http://106.53.97.117:7777/static/combine_{texadr}.docx",f"combine_{texadr}.docx"


#     邮箱方法
    def send_email(self,reciver,pdf_path,docx_path):
        import smtplib
        from email.mime.multipart import MIMEMultipart
        from email.mime.text import MIMEText
        from email.mime.application import MIMEApplication
        # QQ邮箱服务器地址
        mail_host = 'smtp.qq.com'
        # QQ邮箱用户名(即QQ邮箱地址)
        mail_user = '3146838460@qq.com'
        # QQ邮箱密码(这里应填写授权码，而非登录密码)
        mail_pass = 'vfaexsbkiuqidhaf'
        sender = '3146838460@qq.com'
        receivers = [f'{reciver}']  # 接收邮件的邮箱地址
        # 创建一个带附件的实例

        # 创建一个带附件的实例
        msg = MIMEMultipart()
        msg['Subject'] = 'maxstudio 数模神器 极光快递'
        msg['From'] = sender
        msg['To'] = ", ".join(receivers)

        html_content = "<p>这是Maxstudio数模神器今日快递，给您一份您上传赛题的论文框架和解决思路，请您查收哦~😘😘😘</p>"
        msg.attach(MIMEText(html_content, 'html', 'utf-8'))

        # # 添加附件
        docx_path = f'/home/lighthouse/pan/falskapi/src/static/{docx_path}'
        pdf_path = f'/home/lighthouse/pan/falskapi/src/static/{pdf_path}'

        # DOCX附件
        with open(docx_path, "rb") as file:
            docx_attach = MIMEApplication(file.read(), _subtype="docx")
        docx_attach.add_header('Content-Disposition', 'attachment', filename='AIGC-ROT论文指导框架.docx')
        msg.attach(docx_attach)

        # PDF附件
        with open(pdf_path, "rb") as file:
            pdf_attach = MIMEApplication(file.read(), _subtype="pdf")
        pdf_attach.add_header('Content-Disposition', 'attachment', filename='AIGC-ROT论文指导框架.pdf')
        msg.attach(pdf_attach)

        # 发送邮件
        smtpObj = smtplib.SMTP_SSL(mail_host, 465)
        smtpObj.login(mail_user, mail_pass)
        smtpObj.sendmail(sender, receivers, msg.as_string())
        print("Email sent successfully!")
        return "Email sent successfully!"

    # 合并pdf
    def combine_pdf(self,url_pdf_list):
        from PyPDF2 import PdfReader, PdfWriter
        import requests
        from io import BytesIO

        pdf_writer = PdfWriter()

        for url in url_pdf_list:
            response = requests.get(url)
            if response.status_code == 200:
                pdf_reader = PdfReader(BytesIO(response.content))
                for page in range(len(pdf_reader.pages)):
                    pdf_writer.add_page(pdf_reader.pages[page])
            else:
                print(f"无法下载PDF: {url}")

        # 指定输出合并后的PDF文件名称
        relative_name = uuid.uuid4()
        output_filename = f'./static/combine_{str(relative_name)}.pdf'

        # 写入合并后的PDF文件
        with open(output_filename, 'wb') as out:
            pdf_writer.write(out)

        return f"combine_{str(relative_name)}.pdf"

#     处理失效更新：
    def compelte_user(self,name_ids):
        sql = f"update maxstudio_files_table set is_status =1 where name_ids ={name_ids[0]}"
        try:
            result = self.sql_db.query(sql)
            return result
        except Exception as e:
            return e




